package com.lovezy.platform.filestore.service;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyun.oss.model.ResponseHeaderOverrides;
import com.lovezy.platform.common.prop.Constant;
import com.lovezy.platform.core.base.AppServer;
import com.lovezy.platform.core.exception.ServiceException;
import com.lovezy.platform.filestore.exception.FileStoreException;
import com.lovezy.platform.filestore.exception.FileStoreExceptionEnum;
import com.lovezy.platform.filestore.model.File;
import com.lovezy.platform.filestore.oss.OssBucket;
import com.lovezy.platform.filestore.oss.AliOssProperties;
import com.lovezy.platform.filestore.oss.OssBucketChooser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.util.Calendar;
import java.util.Date;


/**
 * Created by jin on 2017/12/18.
 */
public class OssFileHelper implements FileHelper{

    private final Log log = LogFactory.getLog(OssFileHelper.class);

    @Autowired
    protected AliOssProperties properties;

    OssBucketChooser ossBucketChooser;

    private OSSClient ossClient;

    private OSSClient ossExternalClient;


    @Autowired
    private AppServer appServer;

    @PostConstruct
    private void initClient() {
        ossClient = new OSSClient(properties.getEndPoint(), properties.getAccessId(), properties.getSecretKey());
        ossExternalClient = new OSSClient(properties.getExternalEndPoint(), properties.getAccessId(), properties.getSecretKey());

    }


    @Override
    public String toDownloadUrl(String url) {
        if (url == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR, Constant.DOWNLOAD_URL_EXPIRE);
        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(properties.getBucket(), url);
        generatePresignedUrlRequest.setExpiration(calendar.getTime());
        generatePresignedUrlRequest.setMethod(HttpMethod.GET);


        //设置下载的文件名
        ResponseHeaderOverrides responseHeader = new ResponseHeaderOverrides();
        responseHeader.setContentDisposition("attachment;filename=\"" + url + "\"");
        generatePresignedUrlRequest.setResponseHeaders(responseHeader);

        URL downloadUrl =  ossExternalClient.generatePresignedUrl(generatePresignedUrlRequest);
        if (downloadUrl != null) {
            return downloadUrl.toString();
        } else {
            return null;
        }
    }

    @Override
    @Nullable
    public String toDownloadUrl(File file) {
        String url = file.getUrl();
        if (url == null) {
            return null;
        }
        String bucket = file.getDir();
        OssBucket ossBucket = ossBucketChooser.bucketOf(bucket);
        if (ossBucket.isOpen()) {
            return toOpenDownloadUrl(url);
        }else{
            return toDownloadUrl(url);
        }
    }

    private @Nullable String toOpenDownloadUrl(String url) {
        if (!StringUtils.hasText(url)) {
            return null;
        }
        return properties.getOpenUrl() + "/" + url;
    }

    @Override
    public @NotNull byte[] getFileByteArray(File dbFile) {
        return doGetObjectInFile(dbFile, dbFile.getDir());
    }

    protected byte[] doGetObjectInFile(File dbFile,String bucket) {
        String path = toPhysicalPath(dbFile);
        java.io.File file = new java.io.File(path);
        ossClient.getObject(new GetObjectRequest(bucket, dbFile.getUrl()), file);
        try {
            return Files.readAllBytes(file.toPath());
        } catch (IOException e) {
            log.error("读取文件失败", e);
            throw new FileStoreException(FileStoreExceptionEnum.READ_FILE_ERROR);
        }
    }

    @NotNull
    private String toPhysicalPath(@NotNull File file) {
        String savePath = appServer.getFileSavePath();
        return savePath == null ? java.io.File.separator : savePath + file.getDir() + java.io.File.separator + file.getUrl();
    }

    @Override
    public void storeFile(InputStream inputStream, File fileData) {
        doSaveObject(inputStream, fileData, fileData.getDir());
    }

    protected void doSaveObject(InputStream inputStream, File fileData,String bucket) {
        PutObjectResult putObjectResult = ossClient.putObject(bucket, fileData.getUrl(), inputStream);
        ResponseMessage response = putObjectResult.getResponse();
        if (response != null && !response.isSuccessful()) {
            log.error("文件上传Alioss失败 -> " + response.getErrorResponseAsString());
            throw new ServiceException("文件上传失败！");
        }
    }

    @PreDestroy
    public void destory() {
        ossClient.shutdown();
    }

}
